/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
miniob is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details. */

#pragma once

#include "common/type/data_type.h"
#include "storage/common/column.h"
#include "common/value.h"
#include <string>

/**
 * @brief 日期类型（DATE）的具体实现
 * @ingroup DataType
 * @details 继承自 DataType 基类，实现 DATE 类型的比较、运算、类型转换、字符串解析/格式化等核心逻辑
 * 内部基于「1970-01-01 基准天数偏移量」存储，确保高效比较和运算
 */
class DateType : public DataType
{
public:
  /**
   * @brief 构造函数：初始化日期类型为 AttrType::DATE
   */
  DateType() : DataType(AttrType::DATES) {}

  /**
   * @brief 析构函数：默认空实现（无动态资源需释放）
   */
  virtual ~DateType() {}

  /**
   * @brief 比较两个 DATE 类型的 Value 对象
   * @param[in] left 左值（需为 DATE 类型）
   * @param[in] right 右值（需为 DATE 类型）
   * @return int 比较结果：-1（left<right）、0（left==right）、1（left>right）；类型不匹配返回 INT32_MAX
   */
  int compare(const Value &left, const Value &right) const override;

  /**
   * @brief 比较两个 Column 中指定索引的 DATE 类型数据
   * @param[in] left 左列（需为 DATE 类型）
   * @param[in] right 右列（需为 DATE 类型）
   * @param[in] left_idx 左列中要比较的数据索引
   * @param[in] right_idx 右列中要比较的数据索引
   * @return int 比较结果：-1（left<right）、0（left==right）、1（left>right）；类型不匹配返回 INT32_MAX
   */
  int compare(const Column &left, const Column &right, int left_idx, int right_idx) const override;

  /**
   * @brief 日期加法运算（DATE + 整数，整数表示天数）
   * @param[in] left 左值（DATE 类型，基础日期）
   * @param[in] right 右值（INT 类型，要加的天数）
   * @param[out] result 运算结果（DATE 类型，基础日期加天数后的新日期）
   * @return RC 操作结果：SUCCESS（成功）、SCHEMA_FIELD_TYPE_MISMATCH（类型不匹配）、INVALID_DATE（结果日期非法）
   */
  RC add(const Value &left, const Value &right, Value &result) const override;

  /**
   * @brief 日期减法运算（支持两种场景：DATE - 整数 = DATE；DATE - DATE = INT）
   * @param[in] left 左值（DATE 类型）
   * @param[in] right 右值（INT 类型：减天数；DATE 类型：算日期差）
   * @param[out] result 运算结果（DATE 或 INT 类型，需提前设置 result 的类型）
   * @return RC 操作结果：SUCCESS（成功）、SCHEMA_FIELD_TYPE_MISMATCH（类型不匹配）、INVALID_DATE（结果日期非法）
   */
  RC subtract(const Value &left, const Value &right, Value &result) const override;

  /**
   * @brief 日期乘法运算（DATE 类型不支持乘法，直接返回不支持）
   * @param[in] left 左值（未使用）
   * @param[in] right 右值（未使用）
   * @param[out] result 运算结果（未使用）
   * @return RC 固定返回 UNIMPL（未实现）
   */
  RC multiply(const Value &left, const Value &right, Value &result) const override;

  /**
   * @brief 日期取反运算（DATE 类型无实际意义，直接返回不支持）
   * @param[in] val 输入值（未使用）
   * @param[out] result 运算结果（未使用）
   * @return RC 固定返回 UNIMPL（未实现）
   */
  RC negative(const Value &val, Value &result) const override;

  /**
   * @brief 类型转换：将 DATE 类型 Value 转换为目标类型
   * @param[in] val 源值（DATE 类型）
   * @param[in] type 目标类型（支持 CHAR、INT；其他类型返回不支持）
   * @param[out] result 转换后的结果（需提前初始化）
   * @return RC 操作结果：SUCCESS（成功）、SCHEMA_FIELD_TYPE_MISMATCH（目标类型不支持）
   */
  RC cast_to(const Value &val, AttrType type, Value &result) const override;

  /**
   * @brief 计算类型转换成本（用于优化器选择最优转换路径）
   * @param[in] type 目标转换类型
   * @return int 转换成本：0（无成本，同类型）、1（低成本，CHAR/INT）、INT32_MAX（不支持转换）
   */
  int cast_cost(const AttrType type) override;

  /**
   * @brief 从字符串解析日期，设置到 Value 对象
   * @param[out] val 要设置的 Value 对象（结果类型为 DATE）
   * @param[in] data 输入字符串（需为 YYYY-MM-DD 格式，如 "2025-10-01"）
   * @return RC 操作结果：SUCCESS（成功）、SCHEMA_FIELD_TYPE_MISMATCH（格式错误）、INVALID_DATE（日期非法）
   */
  RC set_value_from_str(Value &val, const std::string &data) const override;

  /**
   * @brief 将 DATE 类型 Value 转换为字符串（YYYY-MM-DD 格式）
   * @param[in] val 输入的 DATE 类型 Value
   * @param[out] result 输出的字符串（如 "2025-10-01"）
   * @return RC 操作结果：SUCCESS（成功）、SCHEMA_FIELD_TYPE_MISMATCH（输入非 DATE 类型）
   */
  RC to_string(const Value &val, std::string &result) const override;

private:
  /**
   * @brief 校验日期是否合法（内部辅助函数）
   * @param[in] date_days 日期对应的基准天数（1970-01-01 为 0）
   * @return bool 合法返回 true；非法（超出 1970-01-01 ~ 2038-02-07 范围）返回 false
   */
  bool is_valid_date(int32_t date_days) const;

  /**
   * @brief 将 YYYY-MM-DD 格式字符串解析为date值（内部辅助函数）
   * @param[in] date_str 输入字符串（如 "2025-10-01"）
   * @param[out] date_days 解析后的date值如20241014
   * @return bool 解析成功返回 true；格式错误/日期非法返回 false
   */
  bool parse_date_str(const std::string &date_str, int32_t &date_days) const;

  /**
   * @brief 将date值格式化为 YYYY-MM-DD 字符串（内部辅助函数）
   * @param[in] date_days 输入的date值
   * @param[out] date_str 格式化后的字符串（如 "2025-10-01"）
   * @return bool 格式化成功返回 true；天数非法返回 false
   */
  bool format_date_days(int32_t date_days, std::string &date_str) const;

  // 日期范围常量（1970-01-01 至 2038-02-07 对应的date值）
  static constexpr int32_t MIN_DATE_DAYS = 19700101;        // 1970-01-01
  static constexpr int32_t MAX_DATE_DAYS = 20380207;    // 2038-02-07（32位整数天数上限）
};